<template>
  <div ref="pieChart" :class="{ 'no-data': !data.length }">
    <span v-if="!data.length">暂无数据</span>
  </div>
</template>
<script>
import * as echarts from 'echarts/lib/echarts';
import 'echarts/lib/chart/pie';
import 'echarts/lib/component/title';
import 'echarts/lib/component/grid';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/legend';
import { getScale } from '@/utils/rem';

export default {
  name: 'PieChart',
  props: {
    selectIndex: {
      type: Number,
      default: () => 0,
    },
    grid: {
      type: Object,
      default: () => ({}),
    },
    title: { // 右上角主标题
      type: String,
      default: () => '',
    },
    smallTitle: { // 中上蓝色小标题
      type: String,
      default: () => '',
    },
    data: { // 数据（接口直接取出的数据）
      type: Array,
      default: () => [],
      required: true,
    },
    dataKeys: { // 数据对应key值
      type: Object,
      default: () => ({
        name: 'zbmc',
        value: 'data',
      }),
    },
    seriesOption: { // 不同系列的配置项，封装时会拼到series内
      type: Object,
      default: () => ({}),
      required: true,
    },
    showLegend: { // 是否显示图例
      type: Boolean,
      default: () => true,
    },
    legendOption: { // 图例位置
      type: Object,
      default: () => ({
        left: 'center',
        bottom: 0,
      }),
    },
    total: { // 环状图中心total值展示指标配置项
      type: Object,
      default: () => ({
        show: false,
        text: '',
        value: 0,
        unit: '亿元',
      }),
    },
    showLabel: { // 是否显示label
      type: Boolean,
      default: () => true,
    },
    label: { // label的formatter方法
      type: Function,
      default: (params) => `${params.percent}% ${params.name}`,
    },
    unit: { // 单位
      type: String,
      default: () => '亿元',
    },
    themeColor: { // 主题颜色，包括图例、坐标轴等颜色
      type: String,
      default: () => 'default',
    },
    colors: { // 颜色集
      type: Array,
      default: () => window.global.ECHART_COLORS,
    },
    rem: { // 是否使用rem适配
      type: Boolean,
      default: () => true,
    },
  },
  data() {
    return {
      scale: this.rem ? getScale() : 1,
      chart: null,
      option: {},
      activeIndex: null,
    };
  },
  watch: {
    data: {
      handler: function (newVal, oldVal) {
        this.updateChart();
      },
      immediate: false,
      deep: true,
    },
    selectIndex(val) {
      this.chart.dispatchAction({
        type: 'select',
        seriesIndex: 0, // 系列的索引
        dataIndex: val, // 数据的索引
      });
    },
  },
  mounted() {
    this.initChart();
    this.updateChart();
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$refs.pieChart);
      this.option = {
        grid: {
          left: 0,
          right: 0,
          bottom: 0,
          containLabel: true,
          ...this.grid,
        },
        title: [{
          show: this.title.length > 0,
          text: this.title,
          left: 'center',
          textStyle: {
            color: this.themeColor === 'default' ? '#000' : this.themeColor,
            fontSize: 20 * this.scale,
          },
        }, {
          show: this.smallTitle.length > 0,
          text: this.smallTitle,
          left: this.seriesOption.center ? 0 : 'center',
          textStyle: {
            color: '#3482FF',
            fontSize: 18 * this.scale,
          },
        }, {
          show: this.total.show,
          text: '',
          top: 'middle',
          left: 'center',
          textStyle: {
            color: this.themeColor === 'default' ? '#666' : this.themeColor,
            fontSize: 14 * this.scale,
            rich: {
              value: {
                fontSize: 16 * this.scale,
                lineHeight: 36 * this.scale,
                color: this.themeColor === 'default' ? '#131A2B' : this.themeColor,
              },
            },
          },
        }],
        legend: {
          show: this.showLegend,
          icon: 'circle',
          textStyle: {
            color: '#000',
            fontSize: 16 * this.scale,
          },
          ...this.legendOption,
        },
        tooltip: {
          trigger: 'item',
          textStyle: {
            fontSize: 16 * this.scale,
            fontWeight: 'bold',
          },
          formatter: (params) => {
            return `<div>
                ${params.marker}
                <span style="color: #666;">${params.name}</span>
                <span style="float: right;margin-left: 20px;color: #666;">${params.value !== params.percent ? `${params.value}${this.unit}&nbsp;` : ''}${params.percent}%</span>
              </div>`;
          },
          backgroundColor: 'rgba(255, 255, 255, 0.8)',
          borderWidth: 1,
          borderColor: '#E5E5E5',
          extraCssText: 'box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);',
        },
        color: this.colors,
        series: [{
          type: 'pie',
          label: {
            show: this.showLabel,
            fontSize: 14 * this.scale,
            color: this.themeColor === 'default' ? '#8C8C8C' : this.themeColor,
            formatter: this.label,
            bleedMargin: 0,
          },
          itemStyle: {
            borderWidth: 1 * this.scale,
            borderColor: '#fff',
          },
          emphasis: {
            scale: true,
            scaleSize: 16 * this.scale,
          },
          data: [],
        }],
      };
      this.chart.on('click', (params) => {
        if (params.componentType === 'series') this.$emit('click', params);
      });
      this.chart.on('mouseover', (params) => {
        if (params.componentType === 'series') {
          this.chart.dispatchAction({
            type: 'downplay',
            seriesIndex: 0,
          });
        };
      });
      this.chart.on('legendselectchanged', (params) => {
        this.chart.setOption({
          legend: { selected: { [params.name]: true } },
        });
        setTimeout(() => {
          let activeIndex = Object.keys(params.selected).indexOf(params.name);
          // 高亮当前图形
          this.chart.dispatchAction({
              type: 'highlight',
              seriesIndex: 0,
              dataIndex: activeIndex,
          });
          // 显示 tooltip
          if (params.value || params.value === 0) {
            this.chart.dispatchAction({
              type: 'showTip',
              seriesIndex: 0,
              dataIndex: activeIndex,
            });
          }
          this.activeIndex = activeIndex;
        }, 100);
      });
    },
    updateChart() {
      this.option.title[0].text = this.title;
      this.option.title[1].text = this.smallTitle;
      this.option.title[2].text = (this.total.text ? `${this.total.text}\n` : '') + `{value|${this.total.value}}${this.total.unit}`;
      this.option.series[0] = { ...this.option.series[0], ...this.seriesOption };
      let data = [];
      this.data.forEach((item) => {
        data.push({
          ...item,
          name: item[this.dataKeys.name],
          value: item[this.dataKeys.value],
        });
      });
      this.option.series[0].data = data;
      this.chart.setOption(this.option);
    },
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
      this.chart = null;
    }
  },
};
</script>

<style lang="scss" scoped>
.no-data {
  font-size: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
